package vip.liux.backend.application.serviceImpl.gen;

import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils;
import vip.liux.backend.application.service.gen.AutoMapperProfile;
import vip.liux.backend.application.service.gen.ColumnDto;
import vip.liux.backend.application.service.gen.TableDto;
import vip.liux.backend.domain.models.gen.GenTable;
import vip.liux.backend.domain.models.gen.GenTableColumn;
import vip.liux.backend.infrastructure.constants.GenConst;

import java.util.Arrays;

import static vip.liux.backend.infrastructure.constants.GenConst.*;

public class GenTableUtils {

    private static final char SEPARATOR = '_';

    /**
     * 初始化表信息
     *
     * @param dto 表数据传输对象
     * @return 初始化后的表对象
     */
    public static GenTable initTable(TableDto dto) {
        GenTable table = new GenTable();
        table.setClassName(convertClassName(dto.tableName()));
        table.setModuleName(getModuleName(PACKAGE_NAME));
        table.setPackageName(PACKAGE_NAME);
        table.setTableName(dto.tableName());
        table.setTableComment(dto.tableComment());
        // todo 模块名怎么获取?目前假设为默认值
        table.setGenType(GenConst.GenType.ZIP);
        return table;
    }

    /**
     * 根据列信息构建 GenTableColumn 对象
     *
     * @param tableId   关联的表ID
     * @param columnDto 列信息
     * @return 构建好的 GenTableColumn
     */
    public static GenTableColumn buildTableColumn(Long tableId, ColumnDto columnDto) {
        String dataType = GenTableUtils.getDbType(columnDto.columnType());
        String columnName = columnDto.columnName();

        GenTableColumn column = AutoMapperProfile.INSTANCE.toEntity(columnDto);

        column.setTableId(tableId);
        // 设置Java字段名（驼峰）
        column.setJavaField(GenTableUtils.toCamelCase(columnName));
        // 设置数据库列类型
        column.setColumnType(EnumUtils.getEnumIgnoreCase(ColumnType.class, dataType));
        // 默认Java类型为String
        column.setJavaType(GenConst.JavaType.String);
        // 默认查询类型为等于
        column.setQueryType(GenConst.QueryType.EQUALS);
        // 默认前端控件类型为输入框
        column.setHtmlType(HtmlType.INPUT);

        // region 设置Java 类型和前端控件类型
        // 字符串或文本类型处理
        if (GenTableUtils.arraysContains(COLUMN_TYPE_STR, dataType) || GenTableUtils.arraysContains(COLUMN_TYPE_TEXT, dataType)) {
            Integer columnLength = GenTableUtils.getColumnLength(columnDto.columnType());
            HtmlType htmlType = columnLength >= 500 || GenTableUtils.arraysContains(COLUMN_TYPE_TEXT, dataType)
                    ? HtmlType.TEXTAREA : HtmlType.INPUT;
            column.setHtmlType(htmlType);
        }
        // 时间类型处理
        else if (GenTableUtils.arraysContains(COLUMN_TYPE_TIME, dataType)) {
            column.setJavaType(JavaType.LocalDateTime);
            column.setHtmlType(HtmlType.DATEPICKER);
        }
        // 数值类型处理
        else if (GenTableUtils.arraysContains(COLUMN_TYPE_NUMBER, dataType)) {
            column.setHtmlType(HtmlType.INPUT);
            String[] str = StringUtils.split(StringUtils.substringBetween(columnDto.columnType(), "(", ")"), ",");
            if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) {
                column.setJavaType(JavaType.BigDecimal);
            } else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10) {
                column.setJavaType(JavaType.Integer);
            } else {
                column.setJavaType(JavaType.Long);
            }
        } else if (GenTableUtils.arraysContains(COLUMN_TYPE_BOOL, dataType)) {
            column.setJavaType(JavaType.Boolean);
            column.setHtmlType(HtmlType.RADIO);
        }

        // 根据字段名后缀设置查询类型和前端控件类型
        if (StringUtils.endsWithIgnoreCase(columnName, "name")) {
            column.setQueryType(QueryType.LIKE);
        }
        if (StringUtils.endsWithIgnoreCase(columnName, "status")) {
            column.setHtmlType(HtmlType.RADIO);
        } else if (StringUtils.endsWithIgnoreCase(columnName, "type") || StringUtils.endsWithIgnoreCase(columnName, "sex")) {
            column.setHtmlType(HtmlType.DROPDOWN);
        } else if (StringUtils.endsWithIgnoreCase(columnName, "image") || StringUtils.endsWithIgnoreCase(columnName, "file")) {
            column.setHtmlType(HtmlType.UPLOAD);
        } else if (StringUtils.endsWithIgnoreCase(columnName, "content")) {
            column.setHtmlType(HtmlType.EDITOR);
        }
        // endregion

        boolean isPrimary = Boolean.TRUE.equals(columnDto.primary());
        column.setPrimary(true);
        // 插入字段（默认所有字段都需要插入）
        column.setInsert(true);

        // 父类抽象字段无需插入
        if (GenTableUtils.arraysContains(COLUMN_NAME_NOT_BASE, columnName) && !isPrimary) {
            column.setInsert(false);
        }
        // 可查询字段
        if (!GenTableUtils.arraysContains(COLUMN_NAME_NOT_QUERY, columnName) && !isPrimary) {
            column.setQuery(true);
        }
        // 可编辑字段（排除主键和特殊字段）
        if (!GenTableUtils.arraysContains(COLUMN_NAME_NOT_EDIT, columnName) && !isPrimary) {
            column.setEdit(true);
        }
        // 可列表字段
        if (!GenTableUtils.arraysContains(COLUMN_NAME_NOT_LIST, columnName) && !isPrimary) {
            column.setList(true);
        }

        return column;
    }
    /**
     * 校验数组是否包含指定值
     *
     * @param arr         数组
     * @param targetValue 目标值
     * @return 是否包含
     */
    public static boolean arraysContains(String[] arr, String targetValue) {
        return Arrays.asList(arr).contains(targetValue);
    }

    /**
     * 从包名获取模块名
     *
     * @param packageName 包名
     * @return 模块名
     */
    public static String getModuleName(String packageName) {
        int lastIndex = packageName.lastIndexOf(".");
        int nameLength = packageName.length();
        return StringUtils.substring(packageName, lastIndex + 1, nameLength);
    }

    /**
     * 将表名转换为Java类名
     *
     * @param tableName 表名
     * @return 类名
     */
    public static String convertClassName(String tableName) {
        if (GenConst.AUTO_REMOVE_PRE && StringUtils.isNotEmpty(GenConst.TABLE_PREFIX)) {
            String[] searchList = StringUtils.split(GenConst.TABLE_PREFIX, ",");
            tableName = replaceFirst(tableName, searchList);
        }
        return convertToCamelCase(tableName);
    }

    /**
     * 替换表名前缀
     *
     * @param replace    表名
     * @param searchList 要替换的前缀列表
     * @return 无前缀的表名
     */
    public static String replaceFirst(String replace, String[] searchList) {
        String text = replace;
        for (String searchString : searchList) {
            if (replace.startsWith(searchString)) {
                text = replace.replaceFirst(searchString, "");
                break;
            }
        }
        return text;
    }

    /**
     * 将下划线分隔的字符串转换为驼峰命名法。
     * 如果输入字符串为空，则返回空字符串。
     * 示例: HELLO_WORLD -> HelloWorld
     *
     * @param name 输入字符串
     * @return 驼峰命名法字符串
     */
    public static String convertToCamelCase(String name) {
        StringBuilder result = new StringBuilder();
        if (name == null || name.isEmpty()) {
            return "";
        } else if (!name.contains("_")) {
            return name.substring(0, 1).toUpperCase() + name.substring(1);
        }
        String[] camels = name.split("_");
        for (String camel : camels) {
            if (camel.isEmpty()) {
                continue;
            }
            result.append(camel.substring(0, 1).toUpperCase());
            result.append(camel.substring(1).toLowerCase());
        }
        return result.toString();
    }

    /**
     * 获取数据库类型字段
     *
     * @param columnType 列类型
     * @return 截取后的列类型
     */
    public static String getDbType(String columnType) {
        if (StringUtils.indexOf(columnType, "(") > 0) {
            return StringUtils.substringBefore(columnType, "(");
        } else {
            return columnType;
        }
    }

    /**
     * 驼峰式命名法
     * 例如：user_name->userName
     */
    public static String toCamelCase(String s) {
        if (s == null) {
            return null;
        }
        if (s.indexOf(SEPARATOR) == -1) {
            return s;
        }
        s = s.toLowerCase();
        StringBuilder sb = new StringBuilder(s.length());
        boolean upperCase = false;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            if (c == SEPARATOR) {
                upperCase = true;
            } else if (upperCase) {
                sb.append(Character.toUpperCase(c));
                upperCase = false;
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 获取字段长度
     *
     * @param columnType 列类��
     * @return 截取后的列类型
     */
    public static Integer getColumnLength(String columnType) {
        if (StringUtils.indexOf(columnType, "(") > 0) {
            String length = StringUtils.substringBetween(columnType, "(", ")");
            return Integer.valueOf(length);
        } else {
            return 0;
        }
    }
}
